﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Windows.Forms;
using LockerRack.Exceptions;
using Primitive.Mvvm.Framework.Implementations;
using Primitive.Mvvm.Framework.Interfaces;
using UIController.Controllers;
using UIController.Models;

namespace UIController
{
    public partial class Container : UserControl, IWindowContainer
    {
        private IMediator _mediator;
        private IModel _model;
        private ITaskController _controller;
        private TimerController _timer;

        /// <summary> 
        /// Clean up any resources being used.
        /// </summary>
        /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
        protected override void Dispose(bool disposing)
        {
            if (disposing && (components != null))
            {
                components.Dispose();
            }

            if(_controller != null)
            {
                _controller.Dispose();
            }

            _controller = null;
            _mediator = null;
            _model = null;

            base.Dispose(disposing);
        }

        public Container()
        {
            InitializeComponent();
        }

        public bool Initialize(IModel model, IMediator mediator, List<Exception> exceptions)
        {
            exceptions = exceptions ?? new List<Exception>();

            if (model == null || mediator == null || string.IsNullOrEmpty(model.Path))
            {
                var ex = new Exception("Wrong init object for the main container");
                exceptions.Add(ex);
                return false;
            }

            if (_timer != null)
                _timer.StopReminders();

            _controller = TaskModelController.GetInstance();
            LockerException lex;
            _controller.Initialize(model.Path, out lex);
            if(lex != null)
            {
                exceptions.Add(lex);
                return false;
            }

            _model = new ToDoModel(_controller.Locker);
            _mediator = mediator;

            if (!InitView(_model, _mediator, leftTreeView, exceptions)) 
                return false;

            if (!InitView(_model, _mediator, rightDetailView, exceptions))
                return false;

            if (!InitView(_model, _mediator, bottomView, exceptions))
                return false;

            if (!InitView(_model, _mediator, taskDetailsView1, exceptions))
                return false;

            _timer = new TimerController(_mediator);
            _timer.StartReminders(_model);

            return true;
        }

        private bool InitView(IModel model, IMediator mediator, IWindowContainer view, List<Exception> exceptions)
        {
            var success = view.Initialize(model, mediator, exceptions);
            if (!success)
            {
                exceptions.Add(new Exception(string.Format("Can't create view {0}", view.GetType())));
                return false;
            }
            return true;
        }

        private void OnOpenLocker(object sender, EventArgs e)
        {
            var exceptions = new List<Exception>();

            if(_controller != null && _controller.Locker != null)
            {
                var res = MessageBox.Show(this, "Do you want to save current file?", "Close", MessageBoxButtons.YesNoCancel);
                if (res == DialogResult.Cancel)
                    return;

                var save = res == DialogResult.Yes;
                Exception ex;
                Clear(out ex);
                if(ex != null)
                    exceptions.Add(ex);

                ClearController(save, out ex);
                if (ex != null)
                    exceptions.Add(ex);

                if(exceptions.Count > 0)
                {
                    MessageBox.Show(this, exceptions[0].Message);
                    return;
                }
            }

            var selectedPath = GetOpenPath();

            if(!string.IsNullOrEmpty(selectedPath))
            {
                var vm = new InitModel { Path = selectedPath };
                Initialize(vm, new Mediator(), exceptions);
            }
            
            if(exceptions.Count > 0)
            {
                MessageBox.Show(this, exceptions[0].Message);
            }
        }

        public void Clear(out Exception ex)
        {
            var list = new List<Exception>();
            leftTreeView.Clear(out ex);
            if (ex != null)
                list.Add(ex);
            rightDetailView.Clear(out ex);
            if (ex != null)
                list.Add(ex);
            bottomView.Clear(out ex);
            if (ex != null)
                list.Add(ex);
            taskDetailsView1.Clear(out ex);
            if (ex != null)
                list.Add(ex);
        }

        private void ClearController(bool save, out Exception ex)
        {
            ex = null;
            LockerException lex;
            _controller.Clear(save, out lex);
            if (lex != null)
            {
                ex = lex;
            }
        }
        
        private string GetOpenPath()
        {
            const string ROOT_FOLDER = @"d:\mine\sources\desktop\DropBoxToDo_codeplex\WorkingDir\Locker\";
            var selectedPath = string.Empty;
            using (var fbdlg = new OpenFileDialog())
            {
                fbdlg.InitialDirectory = ROOT_FOLDER;
                fbdlg.FileName = "Empty";
                fbdlg.CheckFileExists = false;
                fbdlg.ValidateNames = false;
                
                if (fbdlg.ShowDialog(this) == DialogResult.OK)
                {
                    selectedPath = fbdlg.FileName;
                    selectedPath = Path.GetDirectoryName(selectedPath);
                }
            }
            return selectedPath;
        }

        private void OnSaveLocker(object sender, EventArgs e)
        {
            if(_controller.Locker != null)
            {
                LockerException ex;
                _controller.Locker.SaveLocker(out ex);
            }
        }
    }
}
